﻿using System.Web.Mvc;
using MyAMS.WebServer.ActionFilter;
using MyAMS.WebServer.Results;
using MyAMS.WebServer.ViewModels;

namespace MyAMS.WebServer.Infrastructure
{
    internal sealed class CustomControllerActionInvoker : ControllerActionInvoker
    {
        private readonly IActionFilterRegistry registry;

        public CustomControllerActionInvoker(IActionFilterRegistry registry)
        {
            this.registry = registry;
        }

        protected override ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
        {
            if (actionReturnValue == null)
            {
                controllerContext.Controller.ViewData.Model = new BaseViewModel();
                return new NotFoundResult();
            }

            if (typeof(ActionResult).IsAssignableFrom(actionReturnValue.GetType()))
            {
                return actionReturnValue as ActionResult;
            }

            controllerContext.Controller.ViewData.Model = actionReturnValue;
            return new ViewResult { ViewData = controllerContext.Controller.ViewData, TempData = controllerContext.Controller.TempData };
        }

        protected override FilterInfo GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
        {
            FilterInfo baseFilters = base.GetFilters(controllerContext, actionDescriptor);
            FilterInfo registeredFilters = registry.GetFilters(controllerContext, actionDescriptor);

            foreach (IActionFilter actionFilter in registeredFilters.ActionFilters)
            {
                baseFilters.ActionFilters.Insert(0, actionFilter);
            }
            foreach (IAuthorizationFilter authorizationFilter in registeredFilters.AuthorizationFilters)
            {
                baseFilters.AuthorizationFilters.Add(authorizationFilter);
            }
            foreach (IExceptionFilter exceptionFilter in registeredFilters.ExceptionFilters)
            {
                baseFilters.ExceptionFilters.Add(exceptionFilter);
            }
            foreach (IResultFilter resultFilter in registeredFilters.ResultFilters)
            {
                baseFilters.ResultFilters.Add(resultFilter);
            }

            return baseFilters;
        }
    }
}
